package com.zjy.business.system.common;

import com.zjy.business.system.dao.SysMenuDao;
import com.zjy.business.system.dao.SysRoleDao;
import com.zjy.business.system.dao.SysUserDao;
import com.zjy.common.constant.StringConstant;
import com.zjy.common.utils.VirtualThreadUtils;
import com.zjy.domain.constant.RedisKeyEnum;
import com.zjy.redis.utils.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author yxb
 * create_time: 2024-10-22 16:28
 * description: 用户角色权限修改公共类
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class SysPermissionCommon {

    final private SysRoleDao sysRoleDao;
    final private SysMenuDao sysMenuDao;
    private final SysUserDao sysUserDao;

    /**
     * 根据用户ID清除该用户的角色和权限信息
     * 此方法主要用于当用户信息发生变化时，清除缓存中的用户角色和权限数据，
     * 以确保数据的一致性和准确性
     *
     * @param userId 用户ID，用于标识特定的用户
     */
    public void clearByUserId(Long userId) {
        clearByUserId(Collections.singletonList(userId));
    }

    /**
     * 根据用户ID清除该用户的角色和权限信息
     * 此方法主要用于当用户信息发生变化时，清除缓存中的用户角色和权限数据，
     * 以确保数据的一致性和准确性
     *
     * @param userIds 用户ID，用于标识特定的用户
     */
    public void clearByUserId(List<Long> userIds) {
        for (Long userId : userIds) {
            VirtualThreadUtils.runAsync(() -> {
                RedisUtils.deleteObject(RedisKeyEnum.USER_ROLE, userId.toString());
                RedisUtils.deleteObject(RedisKeyEnum.USER_PERMISSION, userId.toString());
            });
        }
    }

    /**
     * 根据角色ID清除相关用户信息
     * 此方法首先查询具有特定角色ID的所有用户ID，然后调用另一个方法来清除这些用户的信息
     *
     * @param roleId 角色ID，用于查询用户信息
     */
    public void clearByRoleId(Long roleId) {
        List<Long> userIdList = sysUserDao.getUserIdByRoleId(roleId);
        clearByUserId(userIdList);
    }

    /**
     * 根据菜单ID清除相关用户信息
     *
     * @param menuId 菜单ID，用于标识需要清除的用户信息所关联的菜单
     */
    public void clearByMenuId(Long menuId) {
        List<Long> userIdList = sysUserDao.getUserIdByMenuId(menuId);
        clearByUserId(userIdList);
    }

    /**
     * 获取用户的角色列表
     * @param userId 用户id
     * @return
     */
    public List<String> getUserRoleList(Long userId) {
        List<String> result = RedisUtils.getCacheObject(RedisKeyEnum.USER_ROLE, userId.toString());
        if (Objects.isNull(result)) {
            // 查询数据库,获取用户相关的角色信息
            result = sysRoleDao.getRoleKeyByUserId(userId);
            RedisUtils.setCacheObject(RedisKeyEnum.USER_ROLE, result, userId.toString());
        }
        return result;
    }

    /**
     * 判断用户是否是超级管理员
     *
     * @param adminUserId 管理员用户ID，用于查询用户的角色列表
     * @return 如果用户是超级管理员，则返回true；否则返回false
     */
    public boolean isSuperAdmin(Long adminUserId) {
        List<String> roleList = getUserRoleList(adminUserId);
        if (roleList.contains(StringConstant.ROLE_SUPER_ADMIN)) {
            return true;
        }
        return false;
    }

    /**
     * 根据用户id获取用户权限
     * @param userId 用户id
     */
    public List<String> getUserPermission(Long userId) {
        if(isSuperAdmin(userId)) {
            return List.of(StringConstant.ROLE_SUPER_PERMISSION);
        }
        List<String> result = RedisUtils.getCacheObject(RedisKeyEnum.USER_PERMISSION, userId.toString());
        if (Objects.isNull(result)) {
            // 查询数据库,获取用户相关的权限信息
            result = sysMenuDao.getPermissionByUserId(userId);
            RedisUtils.setCacheObject(RedisKeyEnum.USER_PERMISSION, result, userId.toString());
        }
        return result;
    }
}